﻿using System;
using System.Web;
using log4net;
using MyLib.IO;
using MyLib.Web.Properties;

namespace MyLib.Web.HttpHandlers {
	/// <summary>
	/// 
	/// </summary>
	public abstract class BaseFileHandler : System.Web.IHttpAsyncHandler {
		/// <summary>
		/// Internal logger.
		/// </summary>
		private ILog m_logger = LogManager.GetLogger(typeof(BaseFileHandler));

		#region IHttpHandler Members

		/// <summary>
		/// 
		/// </summary>
		public bool IsReusable {
			get { return true; }
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		/// <param name="cb"></param>
		/// <param name="extraData"></param>
		/// <returns></returns>
		public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {
			Action func = () => {
				ProcessRequest(context);
			};

			return func.BeginInvoke(cb, extraData);

		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="result"></param>
		public void EndProcessRequest(IAsyncResult result) {
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		public void ProcessRequest(HttpContext context) {
			var csection = context.GetSection("mylib.web.fileHandler") as FileHandlerConfigSection;
			if (csection == null) {
				csection = new FileHandlerConfigSection();
			}

			if (csection.AnonymousUsersDenied && !context.Request.IsAuthenticated) {
				throw new HttpException(403, string.Format(Main.FileAccessDenied, context.Request.RawUrl));
			}

			var fp = new FileSystemProvider();
#warning Add configuration.
			fp.SessionFactory = SessionFactory.Create();

			var fileId = context.Request["file_id"];

			try {
				WriteResponse(context, 
					fp.GetFileObject(fileId), 
					fp.GetFileObjectContent(fileId));
			} catch(Exception ex) {
				m_logger.Error(string.Format("Failed to write file \"{0}\".", fileId), ex);
			} finally {
				if (fp.SessionFactory != null) {
					fp.SessionFactory.Close();
				}
			} // end of try.
		}

		#endregion

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		/// <param name="fileObject"></param>
		/// <param name="fileContent"></param>
		protected abstract void WriteResponse(HttpContext context, FileObject fileObject, byte[] fileContent);
	} // end of FileHandler.
}
